package com.note;

import com.note.model.Man;
import com.test02.Person;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.AbstractList;

public class Notes {

    /**
     * 获取类
     * @throws ClassNotFoundException
     */
    public static void baseNote() throws ClassNotFoundException {
        final Class<?> aClass = Class.forName("com.note.model.Man");

        final Class<Man> manClass = Man.class;

        Man man = new Man();
        final Class<? extends Man> aClass1 = man.getClass();
    }

    public static void instanceNote() throws Throwable {
        final Class<Man> manClass = Man.class;
        final Man man1 = manClass.newInstance();
        man1.setName("jia");
        System.out.println(man1.getName());

        Man man = new Man();
        final Class<? extends Man> aClass1 = man.getClass();
        final Man man2 = aClass1.newInstance();

        final Class<?> aClass = Class.forName("com.note.model.Man");
        final Object o = aClass.newInstance();
    }

    public static void classNote() throws Throwable {
        final Class<?> clazz = Class.forName("com.note.model.Man");

        final Object o = clazz.newInstance();

        System.out.println("======================class=======================================");
        System.out.println(clazz.getName());
        System.out.println(clazz.getSimpleName());

        System.out.println("======================field========================================");
        for (Field declaredField : clazz.getDeclaredFields()) {
            System.out.println(declaredField);
        }
        for (Field field : clazz.getFields()) {
            System.out.println(field);
        }
        final Field grade = clazz.getField("grade");
        //final Field sex = clazz.getField("sex"); //NoSuchFieldException没有这个字段异常，因为sex是私有字段

        System.out.println("======================method===========================================");
        for (Method declaredMethod : clazz.getDeclaredMethods()) {
            System.out.println(declaredMethod);
        }
        for (Method method : clazz.getMethods()) {
            System.out.println(method);
        }
        final Method getSex = clazz.getMethod("getSex");
        final Method setSex = clazz.getMethod("setSex", String.class);
        final Method fun = clazz.getMethod("fun", String.class, Integer.class);

        System.out.println("======================Constructor===========================================");
        for (Constructor<?> declaredConstructor : clazz.getDeclaredConstructors()) {
            System.out.println(declaredConstructor);
        }

        System.out.println("======================Annotation===========================================");
        for (Annotation declaredAnnotation : clazz.getDeclaredAnnotations()) {
            System.out.println(declaredAnnotation);
        }

        System.out.println("======================super===========================================");
        final Class<?> superclass = clazz.getSuperclass();
        System.out.println(superclass);
        for (Class<?> anInterface : clazz.getInterfaces()) {
            System.out.println(anInterface);
        }

    }

    public static void fieldNote() throws Throwable {
        final Class<?> clazz = Class.forName("com.note.model.Man");
        final Object instance = clazz.newInstance();
        final Field grade = clazz.getField("grade");

        System.out.println(grade.getName());

        final int modifiers = grade.getModifiers();
        System.out.println(modifiers);
        System.out.println(Modifier.toString(modifiers));

        final Class<?> type = grade.getType();
        System.out.println(type);
        System.out.println(type.getSimpleName());

        System.out.println(grade.get(instance));
        grade.set(instance, "aaa");
        System.out.println(grade.get(instance));

        decompileField();
    }

    public static void decompileField() throws Throwable {
        StringBuilder s = new StringBuilder();

        Class<?> studentClass = Class.forName("com.note.model.Man");
        s.append(Modifier.toString(studentClass.getModifiers())).append(" class ").append(studentClass.getSimpleName()).append(" {\n");// Class类的getName方法
        //获取所有的属性
        Field[] fields = studentClass.getDeclaredFields();
        for (Field f : fields){
            s.append("\t");
            // 获取属性的修饰符列表,返回的修饰符是一个数字，每个数字是修饰符的代号
            // 用Modifier类的toString转换成字符串
            s.append(Modifier.toString(f.getModifiers()));
            if (f.getModifiers() != 0) s.append(" ");
            s.append(f.getType().getSimpleName());// 获取属性的类型
            s.append(" ");
            s.append(f.getName());// 获取属性的名字
            s.append(";\n");
        }
        s.append("}");
        System.out.println(s);
    }

    public static void methodNote() throws Throwable {
        final Class<?> clazz = Class.forName("com.note.model.Man");
        final Object instance = clazz.newInstance();
        final Method fun = clazz.getMethod("fun", String.class, Integer.class);
        fun.invoke(instance, "jia", 10);
    }

    public static void constructorNote() throws Throwable {
        final Class<?> clazz = Class.forName("com.note.model.Man");
        final Object instance = clazz.newInstance(); //无参构造的简化使用
        final Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
        final Object o = declaredConstructor.newInstance("aaa", "bbb");
    }

    public static void main(String[] args) throws Throwable {
        constructorNote();
    }
}
